/**
    Copyright (C) 2011  Alexander Vollmer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.jefb.aop;

import java.lang.reflect.Field;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.jefb.annotations.EnabledHavingRights;
import org.jefb.sec.entity.UserRight;
import org.jefb.service.IUserSessionService;
import org.jefb.service.impl.UserSessionService;
import org.springframework.context.annotation.Scope;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.zkoss.zk.ui.ext.Disable;

@org.springframework.stereotype.Component
@Scope("prototype")
@Aspect
public class DisableAspect {

	@Pointcut(value = "execution(* org.jefb.web.controller.*.doAfterCompose(..))")
	public void afterCompose() {
	}

	@Around("afterCompose()")
	public Object aroundAdvice(ProceedingJoinPoint call) throws Throwable {
		Object result = call.proceed();
		applyUserRightsToUIComponents(call);
		return result;
	}

	/**
	 * Apply user rights to the ui components.
	 * @param call
	 * @throws IllegalAccessException
	 */
	private void applyUserRightsToUIComponents(ProceedingJoinPoint call)
			throws IllegalAccessException {
		//get current web application context
		WebApplicationContext currentWebApplicationContext = ContextLoader
				.getCurrentWebApplicationContext();
		//find user session service in spring context
		UserSessionService userSession = (UserSessionService) currentWebApplicationContext
				.getBean(IUserSessionService.COMPONENT_NAME);
		//apply only if session exists and user isn't a superuser
		if (userSession != null && !userSession.getAllUserRights().contains(UserRight.ALL)) {
			Object uiController = call.getTarget();
			Field[] fields = uiController.getClass().getDeclaredFields();
			for (Field field : fields) {
				//enable field access
				field.setAccessible(true);
				//find marker annotation
				EnabledHavingRights enableMarker = field
						.getAnnotation(EnabledHavingRights.class);
				if (enableMarker != null) {
					UserRight[] enabledRights = enableMarker.value();
					//fetch the field-object from the controller
					Object uiObject = field.get(uiController);
					//check if UI component can be disabled
					if (uiObject instanceof Disable) {
						Disable uiComponent = (Disable) uiObject;
						//check rights specified for current UI component
						for (UserRight right : enabledRights) {
							if (userSession.getAllUserRights().contains(
									right)) {
								uiComponent.setDisabled(false);
								break;
							}
							uiComponent.setDisabled(true);
						}
					}
				}
			}
		}
	}
}
